import 'package:flutter/material.dart';

import 'focus_utils.dart';

///项目路由工具类
///可通过该类的静态方法进行路由操作
///另外也对BuildContext进行了函数扩展，可以通过BuildContext对象进行对Nav的调用，详情查看NavExtension
class Nav {
  static final GlobalKey<NavigatorState> globalNavigatorKey =
      GlobalKey<NavigatorState>();

  ///通过Router对象跳转，一般情况下尽量不使用该方法，请通过路由名跳转
  static Future<T?> pushPage<T extends Object?>(
      {BuildContext? context, required Widget page}) {
    Route<T> route = MaterialPageRoute(builder: (context) => page);
    if (context == null) {
      return _getGlobalNavigatorState().push(route);
    } else {
      FocusUtil.cancelFocus(context);
      return Navigator.of(context).push(route);
    }
  }

  ///通过Router对象跳转，一般情况下尽量不使用该方法，请通过路由名跳转
  static Future<T?> pushRouter<T extends Object?>(
      {BuildContext? context, required Route<T> route}) {
    if (context == null) {
      return _getGlobalNavigatorState().push(route);
    } else {
      FocusUtil.cancelFocus(context);
      return Navigator.of(context).push(route);
    }
  }

  ///通过路由名称跳转至新路由
  ///一般情况下尽量传Context
  ///返回值：通过Future接收页面数据返回对象
  static Future<T?> push<T extends Object?>(
      {BuildContext? context,
      required String routerName,
      Map<String, dynamic>? arguments}) {
    if (context == null) {
      return _getGlobalNavigatorState()
          .pushNamed(routerName, arguments: arguments);
    } else {
      FocusUtil.cancelFocus(context);
      return Navigator.of(context).pushNamed(routerName, arguments: arguments);
    }
  }

  ///通过路由名称跳转至新路由，并且结束当前页面
  ///一般情况下尽量传Context
  ///返回值：通过Future接收页面数据返回对象
  static Future<T?> pushReplacement<T extends Object?>(
      {BuildContext? context,
      required String routerName,
      Map<String, dynamic>? arguments}) {
    if (context == null) {
      return _getGlobalNavigatorState()
          .pushReplacementNamed(routerName, arguments: arguments);
    } else {
      FocusUtil.cancelFocus(context);
      return Navigator.of(context)
          .pushReplacementNamed(routerName, arguments: arguments);
    }
  }

  ///通过路由名称跳转至新路由，并且批量结束页面，直到predicate返回true
  ///一般情况下尽量传Context
  ///返回值：通过Future接收页面数据返回对象
  ///,required RoutePredicate predicate
  static Future<T?> pushAndClear<T extends Object?>(
      {BuildContext? context,
      required String routerName,
      Map<String, dynamic>? arguments}) {
    if (context == null) {
      return _getGlobalNavigatorState().pushNamedAndRemoveUntil(
          routerName, (route) => false,
          arguments: arguments);
    } else {
      FocusUtil.cancelFocus(context);
      return Navigator.of(context).pushNamedAndRemoveUntil(
          routerName, (route) => false,
          arguments: arguments);
    }
  }

  ///弹出当前页面，并且可以
  ///一般情况下尽量传Context
  static void pop<T extends Object?>({BuildContext? context, T? result}) {
    if (context == null) {
      _getGlobalNavigatorState().pop(result);
    } else {
      Navigator.pop(context, result);
    }
  }

  ///批量结束页面，直到predicate返回true
  ///一般情况下尽量传Context
  static void popUntil<T extends Object?>(
      {BuildContext? context, required RoutePredicate predicate}) {
    if (context == null) {
      _getGlobalNavigatorState().popUntil(predicate);
    } else {
      Navigator.popUntil(context, predicate);
    }
  }

  ///全局NaigatorState，在某些没Context的下，可通过该对象进行路由操作
  static NavigatorState _getGlobalNavigatorState() {
    return globalNavigatorKey.currentState!;
  }

  ///获取当前页面传参数据，也可通过BuildContext的getRouterArgument获得;
  static dynamic getRouterArgument({BuildContext? context}) {
    context ??= _getGlobalNavigatorState().context;
    return ModalRoute.of(context)?.settings.arguments;
  }
}
